#include "IdentifyHistories.h"

//////////////////////////////////////////////////////////////////////////
//Author	:	Ross Conroy ross.conroy@tees.ac.uk
//Date		:	28/10/2014
//
//This class is used to identify histories in replay data based on
//Learning predictive State Representations Without Reset
//////////////////////////////////////////////////////////////////////////

IdentifyHistories::IdentifyHistories(void)
{
}


//////////////////////////////////////////////////////////////////////////
//Extracts rows from data before passing it onto zero history for processing
//////////////////////////////////////////////////////////////////////////
void IdentifyHistories::Identify(string inputFile, string outputFile, string stateCol, string obsCol, string actionCol, int maxHistory)
{
	DataRowFile dataRowFile;
	list<DataRow> rows = dataRowFile.FileToRows(inputFile, stateCol, obsCol, actionCol);
	rows = Identify(rows, maxHistory);
	dataRowFile.RowsToFile(outputFile, rows, stateCol, obsCol, actionCol);
}

//////////////////////////////////////////////////////////////////////////
//Looks at each action trying to identify the history for each
//////////////////////////////////////////////////////////////////////////
list<DataRow> IdentifyHistories::Identify(list<DataRow> dataRows, int maxHistory)
{
	for(list<DataRow>::iterator itd = dataRows.begin(); itd != dataRows.end(); itd++)
	{
		int maxHistorySize = 0;

		//for each history length check number of matches and same actions in data
		for(int hs = 0; hs < maxHistory; hs++)
		{
			int tempH = hs;
			DataRow currentRow = *itd;
			list<DataRow> history;
			for(list<DataRow>::iterator itdr = itd; (itdr != dataRows.begin()) && (tempH >= 0); itdr--)
			{	
				history.push_front(*itdr);
				tempH --;
			}

			int historyCount = 0;
			int historyActionCount = 0;

			for(list<DataRow>::iterator itdh = dataRows.begin(); itdh != dataRows.end(); itdh++)
			{
				tempH = hs;
				bool tempLandmarkFound = false;
				list<DataRow> tempHistory;				
				for(list<DataRow>::iterator itdr = itdh; (itdr!= dataRows.begin()) && (tempH >= 0); itdr--)
				{	
					tempHistory.push_front(*itdr);
					tempH --;
				}

				//Both histories must be same length
				int currentHistItem = 0;
				if(tempHistory.size() == history.size())
				{
					bool matchHist = true;
					bool matchAction = true;

					list<DataRow>::iterator itth = tempHistory.begin();
					for(list<DataRow>::iterator ith = history.begin(); ith != history.end() && matchHist; ith++)
					{
						DataRow currHistRow = *ith;
						DataRow currTempHistRow = *itth;

						//Only interested in action on first step of history so only allow observation checks when not 0
						if(currentHistItem != 0)
						{
							if(currHistRow.observation != currTempHistRow.observation)
							{
								matchHist = false;
							}
						}

						//only use action in final if not the final history item to check
						if(currentHistItem != hs)
						{
							if(currentRow.action != currTempHistRow.action)
							{
								matchHist = false;
							}
						}
						else
						{
							//Keep a record of is the last actions matched used for later calculations
							if(currentRow.action != currTempHistRow.action)
							{
								matchAction = false;
							}
							else
							{
								matchAction = true;
							}
						}

						currentHistItem ++;
						itth ++;
					}

					//if histories match, finally check final action in each history for a match
					if(matchHist)
					{
						historyCount ++;
						if(matchAction)
						{
							historyActionCount ++;
						}
					}
				}

				//Compare ratio of history occurrences and action outcomes
				if((historyCount > 1) && (historyActionCount > 1))
				{
					if(historyCount == historyActionCount)
					{
						maxHistorySize = hs;
					}
				}
			}
		}

		itd->historyLength = maxHistorySize;
	}

	return dataRows;
}